package org.simple.framework.core.inject;

import lombok.extern.slf4j.Slf4j;
import org.simple.framework.core.inject.annotation.Autowired;
import org.simple.framework.core.util.BeanContainer;
import org.simple.framework.core.util.ClassUtil;
import org.simple.framework.core.util.ValidationUtil;

import java.lang.reflect.Field;
import java.util.Set;

/**
 * @author ：zhanghaixuan
 * @date ：Created in 2020/3/7 10:31 下午
 * 用途         ： TODO
 */
@Slf4j
public class DependecyInjector {

    private BeanContainer beanContainer;

    public DependecyInjector(){
        beanContainer = BeanContainer.getInstance();
    }

    /**
     * 执行iod
     */
    public void doIoc(){
        /**
         * 获取容器内部的全部class
         */
        Set<Class<?>> classes = beanContainer.getClasses();
        /**
         * 遍历Class对象中的所有成员为空
         */
        if (ValidationUtil.collectionIsEmpty(classes)) {
            log.warn("beanContainer 中没有任何对象");
            return;
        }

        for (Class<?> aClass : classes) {
            Field[] declaredFields = aClass.getDeclaredFields();

            if (ValidationUtil.arrayIsEmpty(declaredFields)) {
                return;
            }

            /**
             * 找出被Autowired标记的成员变量
             */
            for (Field declaredField : declaredFields) {
                if(declaredField.isAnnotationPresent(Autowired.class)){
                    Autowired annotation = declaredField.getAnnotation(Autowired.class);
                    /**
                     * 获取属性值
                     */
                    String value = annotation.value();
                    /**
                     * 获取成员变量的类型
                     */
                    Class<?> type = declaredField.getType();
                    /**
                     * 获取需要注入的实例
                     */
                    Object output = getFieldInstance(type,value);

                    if(null == output){
                        throw new RuntimeException("获取依赖注入实例失败,targer:"+type.getName()+"vlaue:"+value);
                    }else{
                        /**
                         * 通过反射注入
                         */
                        Object bean = beanContainer.getBean(aClass);

                        ClassUtil.setField(declaredField,bean,output,true);
                    }
                }
            }
        }
    }

    /**
     * 根据class在beanContainer 找到他的实例或者实现类
     * @param type 参数类型
     * @param value 获取的实例名称
     * @return
     */
    private Object getFieldInstance(Class<?> type, String value) {

        Object bean = beanContainer.getBean(type);

        if(null != bean){
            return bean;
        }else{
            Class<?> implementClass =getImplementClass(type,value);

            if(implementClass != null){
                return beanContainer.getBean(implementClass);
            }
        }

        return null;
    }

    /**
     * 获取接口的实现类
     * @param type
     * @param value
     * @return
     */
    private Class<?> getImplementClass(Class<?> type, String value) {
        Set<Class<?>> classesBySuper = beanContainer.getClassesBySuper(type);

        if (!ValidationUtil.collectionIsEmpty(classesBySuper)) {
            if(ValidationUtil.strIsEmpty(value)){
                if (classesBySuper.size()==1) {
                    return classesBySuper.iterator().next();
                }else {
                    throw new RuntimeException(type+"有多个实现");
                }
            }else {
                for (Class<?> aClass : classesBySuper) {
                    if (value.equalsIgnoreCase(aClass.getSimpleName())) {
                        return aClass;
                    }
                }
            }
        }

        return null;
    }
}
